package com.atguigu.yygh.order.service.impl;


import com.alibaba.fastjson.JSONObject;
import com.atguigu.yygh.common.exception.YyghException;
import com.atguigu.yygh.enums.OrderStatusEnum;
import com.atguigu.yygh.enums.PaymentStatusEnum;
import com.atguigu.yygh.enums.PaymentTypeEnum;
import com.atguigu.yygh.enums.RefundStatusEnum;
import com.atguigu.yygh.model.order.OrderInfo;
import com.atguigu.yygh.model.order.PaymentInfo;
import com.atguigu.yygh.model.order.RefundInfo;
import com.atguigu.yygh.order.pojo.WeiPay;
import com.atguigu.yygh.order.service.OrderInfoService;
import com.atguigu.yygh.order.service.PaymentInfoService;
import com.atguigu.yygh.order.service.RefundInfoService;
import com.atguigu.yygh.order.service.WxPayService;
import com.atguigu.yygh.order.utils.HttpClient;
import com.atguigu.yygh.order.utils.HttpRequestHelper;
import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayUtil;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author luoyin
 * @Date 19:33 2022/10/10
 **/
@Service
public class WxPayServiceImpl implements WxPayService {
   @Autowired
   private OrderInfoService orderInfoService;
   @Autowired
   private PaymentInfoService paymentInfoService;
   @Autowired
   private RefundInfoService refundInfoService;

    @Override
    public String createNative(Long orderId) throws Exception {
        PaymentInfo paymentInfo = new PaymentInfo();
        OrderInfo orderInfo = orderInfoService.getById(orderId);
        paymentInfo.setOrderId(orderId);
        paymentInfo.setOutTradeNo(orderInfo.getOutTradeNo());
        paymentInfo.setPaymentType(PaymentTypeEnum.WEIXIN.getStatus());
        paymentInfo.setTotalAmount(orderInfo.getAmount());
        paymentInfo.setSubject("有钱真好");
        paymentInfo.setPaymentStatus(PaymentStatusEnum.UNPAID.getStatus());
        paymentInfoService.insert(paymentInfo);


        Map<String, String> map = new HashMap<>();
        map.put("appid", WeiPay.APPID);
        map.put("mch_id", WeiPay.PARTENER);
        map.put("out_trade_no",orderInfo.getOutTradeNo());
        map.put("nonce_str",WXPayUtil.generateNonceStr());
        map.put("body","有钱人");
        map.put("total_fee","1");
        map.put("spbill_create_ip","127.0.0.1");
        map.put("notify_url","http://guli.shop/api/order/weixinPay/weixinNotify");
        map.put("trade_type","NATIVE");
        HttpClient httpClient = new HttpClient("https://api.mch.weixin.qq.com/pay/unifiedorder");
        httpClient.setXmlParam(WXPayUtil.generateSignedXml(map, WeiPay.PARTNERKAY));
        httpClient.setHttps(true);
        httpClient.post();

        //接受的数据
        String content = httpClient.getContent();
        Map<String, String> xmlToMap = WXPayUtil.xmlToMap(content);
        if (!xmlToMap.get("result_code").equals("SUCCESS") ){
            return "";
        }
        return xmlToMap.get("code_url");
    }

    @Override
    public Map<String, String> queryPayStatus(Long orderId) throws Exception {

        OrderInfo orderInfo = orderInfoService.getById(orderId);
        Map<String, String> map = new HashMap<>();
        map.put("appid", WeiPay.APPID);
        map.put("mch_id", WeiPay.PARTENER);
        map.put("out_trade_no",orderInfo.getOutTradeNo());
        map.put("nonce_str",WXPayUtil.generateNonceStr());
        HttpClient httpClient = new HttpClient("https://api.mch.weixin.qq.com/pay/orderquery");
        httpClient.setXmlParam(WXPayUtil.generateSignedXml(map, WeiPay.PARTNERKAY));
        httpClient.setHttps(true);
        httpClient.post();

        //接受的数据
        String content = httpClient.getContent();

        return WXPayUtil.xmlToMap(content);
    }

    @Override
    @Transactional
    public void updatePayStatus(Long orderId, Map<String, String> map) {
        //修改订单状态
        orderInfoService.updatePayStatus(orderId, OrderStatusEnum.PAID.getStatus());
        //修改支付状态
        paymentInfoService.updatePayStatus(orderId,map);
        //修改第三方医院
        HashMap<String, Object> requestMap = new HashMap<>();
        OrderInfo orderInfo = orderInfoService.getById(orderId);
        requestMap.put("hoscode",orderInfo.getHoscode());
        requestMap.put("hosRecordId",orderInfo.getHosRecordId());
        JSONObject jsonObject = HttpRequestHelper.sendRequest(requestMap,"http://localhost:9998/order/updatePayStatus");
        if(jsonObject == null || jsonObject.getInteger("code") != 200){
            throw new YyghException(20001,"修改第三方医院状态失败!");
        }
    }

    @Override
    public Boolean refund(Long orderId) throws Exception {
        OrderInfo orderInfo = orderInfoService.getById(orderId);
        //查询退款记录需要的数据
        PaymentInfo paymentInfo = paymentInfoService.getByOrderIdAndStatus(orderId, PaymentTypeEnum.WEIXIN.getStatus());
        //保存到退款记录
        RefundInfo refundInfo = refundInfoService.saveRefundInfo(paymentInfo);
        if (refundInfo.getRefundStatus().intValue() == RefundStatusEnum.REFUND.getStatus().intValue()){
            //如果已经退款
            return true;
        }
        HashMap<String, String> map = new HashMap<>();
        map.put("appid",WeiPay.APPID);
        map.put("mch_id",WeiPay.PARTENER);
        map.put("nonce_str",WXPayUtil.generateNonceStr());
        map.put("out_trade_no",orderInfo.getOutTradeNo());
        map.put("out_refund_no","tk"+orderInfo.getOutTradeNo()+new DateTime().toString("yyyyMMddHHmmss"));
        map.put("total_fee","1");
        map.put("refund_fee","1");
        String signedXml = WXPayUtil.generateSignedXml(map, WeiPay.PARTNERKAY);
        HttpClient httpClient = new HttpClient("https://api.mch.weixin.qq.com/secapi/pay/refund");
        httpClient.setCert(true);
        httpClient.setCertPassword(WeiPay.PARTENER);
        httpClient.setXmlParam(signedXml);
        httpClient.setHttps(true);
        httpClient.post();
        Map<String, String> xmlToMap = WXPayUtil.xmlToMap(httpClient.getContent());
        if (null != xmlToMap && "SUCCESS".equals(xmlToMap.get("result_code"))){
            refundInfo.setCallbackTime(new Date());
            refundInfo.setRefundStatus(RefundStatusEnum.REFUND.getStatus());
            refundInfo.setCallbackContent(xmlToMap.toString());
            refundInfo.setTradeNo(xmlToMap.get("refund_id"));
            refundInfoService.updateById(refundInfo);
            return true;
        }
        return false;
    }
}
